package com.wang.application.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.application.api.user.LoginRequest;
import com.wang.application.api.user.LoginResponse;
import com.wang.application.api.user.RegisterRequest;
import com.wang.application.api.user.UpdateRequest;
import com.wang.application.mapper.DaUserMapper;
import com.wang.application.model.DaUser;
import com.wang.application.service.DaUserService;
import com.wang.common.common.AService;
import com.wang.common.common.ErrorCode;
import com.wang.common.exception.BusinessException;
import com.wang.common.model.RUser;
import com.wang.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Objects;

/**
* @author Mr.wang
* @description 针对表【da_user(用户表)】的数据库操作Service实现
* @createDate 2022-11-02 10:01:21
*/
@Service
@Slf4j
public class DaUserServiceImpl extends ServiceImpl<DaUserMapper, DaUser>
    implements DaUserService{

    @Resource
    private AService aService;

    @Resource
    private DaUserMapper daUserMapper;

    @Resource
    private RedisUtil redisUtil;

    @Value("${head.file.path}")
    private String headImage;

    @Override
    public Boolean register(RegisterRequest request) {
        log.info("=========================RegisterRequest：{}", request);

        // 1.校验
        if (Utils.isAnyBlank(request.getUsername(), request.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (Utils.hasSpecialChar(request.getUsername())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号包含特殊字符");
        }
        if (request.getUsername().length() < 4 || request.getUsername().length() > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度错误");
        }
        if (Utils.isNotEmpty(request.getNickname()) && (request.getNickname().length() < 4 || request.getNickname().length() > 20)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "昵称长度错误");
        }
        if (request.getPassword().length() < 8 || request.getCheckPassword().length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度过短");
        }
        if (!request.getPassword().equals(request.getCheckPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码与校验密码不一致");
        }
        QueryWrapper<DaUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", request.getUsername());
        Long count;
        try {
            count = daUserMapper.selectCount(queryWrapper);
        } catch (Exception e) {
            log.error("数据库查询失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据库查询失败");
        }
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
        }

        // 2.插入数据
        DaUser daUser = request.transfer();
        boolean save;
        try {
            save = this.save(daUser);
        } catch (Exception e) {
            log.error("注册账号插入数据库失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册账号插入数据库失败");
        }

        // 3.存入attribute
        QueryWrapper<DaUser> cooWra = new QueryWrapper<>();
        cooWra.eq("username", request.getUsername());
        try {
            daUser = daUserMapper.selectOne(cooWra);
        } catch (Exception e) {
            log.error("查询注册用户信息失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "查询注册用户信息失败");
        }
        aService.getReq().setAttribute("userId", daUser.getUserid());
        return save;
    }

    @Override
    public LoginResponse login(LoginRequest request) {
        log.info("=========================LoginRequest：{}", request);

        if (Utils.isAnyBlank(request.getUsername(), request.getPassword())
                || request.getUsername().length() < 4
                || Utils.hasSpecialChar(request.getUsername())
                || request.getPassword().length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数错误");
        }
        // 查询用户是否存在
        DaUser transfer = request.transfer();
        QueryWrapper<DaUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", transfer.getUsername());
        queryWrapper.eq("password", transfer.getPassword());
        queryWrapper.eq("status", Contact.Status.ACTIVE);
        DaUser daUser;
        try {
            daUser = daUserMapper.selectOne(queryWrapper);
        } catch (Exception e) {
            log.error("数据库查询失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据库查询失败");
        }
        if (daUser == null || "0".equals(daUser.getStatus())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        // 用户脱敏
        LoginResponse safetyUser = getSafetyData(daUser);
        // 记录用户登录态
        aService.getReq().setAttribute("userId", daUser.getUserid());
        String token = TokenUtil.getToken(daUser.getUsername(), daUser.getPassword());
        safetyUser.setToken(token);
        RUser rUser = getRUser(daUser);
        redisUtil.setString(token, Utils.objToJsonString(rUser));
        Utils.XMLParse(safetyUser, LoginResponse.class);
        return safetyUser;
    }

    @Override
    public Boolean logout() {
        log.info("=========================logout");
        String token = aService.getReq().getHeader("token");
        redisUtil.deleteString(token);
        return true;
    }

    @Override
    public DaUser uploadHeadImage(MultipartFile file) {
        log.info("=========================uploadHeadImage");

        String oldName = file.getOriginalFilename();
        String newName = FileUtil.getFileName(Objects.requireNonNull(oldName).substring(oldName.lastIndexOf(".")));
        try {
            FileUtil.saveImageFile(file.getInputStream(), newName, headImage);
        } catch (IOException e) {
            log.error("头像保存失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "头像保存失败");
        }
        DaUser daUser = new DaUser();
        daUser.setHeadimage(aService.getHeadPrefix() + newName);
        return daUser;
    }

    @Override
    public DaUser updateUserInfo(UpdateRequest request) {
        log.info("=========================UpdateRequest:{}", request);

        // 校验
        if (Utils.isEmpty(request.getUserid())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数错误");
        }
        DaUser daUser;
        try {
            daUser = daUserMapper.selectById(request.getUserid());
        } catch (Exception e) {
            log.error("数据库查询失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据库查询失败");
        }
        if (daUser == null || "0".equals(daUser.getStatus())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        if (Utils.isNotEmpty(request.getPassword()) && Utils.isNotEmpty(request.getCheckPassword()) && (request.getPassword().length() < 8 || request.getCheckPassword().length() < 8)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度过短");
        }
        if (Utils.isNotEmpty(request.getPassword()) && Utils.isNotEmpty(request.getCheckPassword()) && !request.getPassword().equals(request.getCheckPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码和校验密码不一致");
        }
        if (Utils.isNotEmpty(request.getNickname()) && (request.getNickname().length() < 4 || request.getNickname().length() > 20)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "昵称长度错误");
        }
        boolean result;
        DaUser transfer = request.transfer();
        UpdateWrapper<DaUser> updateWrapper = MybatisUtil.updateFilter(transfer);
        updateWrapper.eq("userid", transfer.getUserid());
        try {
            result = update(updateWrapper);
        } catch (Exception e) {
            log.error("用户信息修改失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据库修改失败");
        }
        if (!result) throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户信息修改失败");
        QueryWrapper<DaUser> que = new QueryWrapper<>();
        que.eq("userid", transfer.getUserid());
        try {
            transfer = daUserMapper.selectOne(que);
        } catch (Exception e) {
            log.error("用户信息查询失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户信息查询失败");
        }
        DaUser safetyData = getUpdateData(transfer);
        Utils.XMLParse(safetyData, DaUser.class);
        return safetyData;
    }

    @Override
    public Boolean forgetPassword(UpdateRequest request) {
        log.info("=========================forgetPassword:{}", request);

        // 校验
        if (Utils.isAnyBlank(request.getUsername(), request.getPassword(), request.getCheckPassword(), request.getProblem1(), request.getAnswer1())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数错误");
        }
        DaUser daUser;
        QueryWrapper<DaUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", request.getUsername());
        try {
            daUser = daUserMapper.selectOne(queryWrapper);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户信息查询失败");
        }
        if (daUser == null || "0".equals(daUser.getStatus())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        if (!daUser.getProblem1().equals(request.getProblem1()) || !daUser.getAnswer1().equals(request.getAnswer1())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "问题或答案不正确");
        }
        if (request.getPassword().length() < 8 || request.getCheckPassword().length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度过短");
        }
        if (!request.getPassword().equals(request.getCheckPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码与校验密码不一致");
        }
        // 保存数据
        DaUser saveUser = new DaUser();
        saveUser.setPassword(Utils.encodePassword(request.getPassword()));
        UpdateWrapper<DaUser> updateWrapper = MybatisUtil.updateFilter(saveUser);
        updateWrapper.eq("username", request.getUsername());
        boolean result;
        try {
            result = update(updateWrapper);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据库修改密码失败");
        }
        aService.getReq().setAttribute("userId", daUser.getUserid());
        return result;
    }

    /**
     * 用户脱敏
     */
    private LoginResponse getSafetyData(DaUser da) {
        LoginResponse daUser = new LoginResponse();
        daUser.setUserid(da.getUserid());
        daUser.setUsername(da.getUsername());
        daUser.setNickname(da.getNickname());
        daUser.setHeadimage(da.getHeadimage());
        daUser.setAuthid(da.getAuthid());
        daUser.setStatus(da.getStatus());
        return daUser;
    }

    private DaUser getUpdateData(DaUser da) {
        DaUser daUser = new DaUser();
        daUser.setUserid(da.getUserid());
        daUser.setUsername(da.getUsername());
        daUser.setNickname(da.getNickname());
        daUser.setHeadimage(da.getHeadimage());
        daUser.setAuthid(da.getAuthid());
        daUser.setStatus(da.getStatus());
        return daUser;
    }

    /**
     * DaUser transfer RUser
     */
    private RUser getRUser(DaUser da) {
        RUser rUser = new RUser();
        rUser.setUserid(da.getUserid());
        rUser.setUsername(da.getUsername());
        rUser.setPassword(da.getPassword());
        rUser.setNickname(da.getNickname());
        rUser.setAuthid(da.getAuthid());
        rUser.setHeadimage(da.getHeadimage());
        rUser.setStatus(da.getStatus());
        rUser.setProblem1(da.getProblem1());
        rUser.setAnswer1(da.getAnswer1());
        return rUser;
    }
}




